package server;

public class DatabaseGuard {
	private Database db;
	private ActiveUser au;
	private String block = "Du saknar behorighet for denna information.";
	private String pass = "Du far lasa den har informationen.";

	/**Creates a database guard which supervises access to the database and prevents
	 * the client from receiving privileged information.
	 * @param db the database object to guard
	 */
	public DatabaseGuard(Database db) {
		this.db = db;
		au = null;
	}
	
	/**Gets the salt associated with the CN/username
	 * @param commonName the CN extracted from a x509
	 * @return String of the salt or "" if no salt was found
	 */
	public String getSalt(String commonName) {
		String salt = db.findSalt(commonName);
		if (salt != null) {
			return salt; 
		}
		return "";
	}

	/** Logs in a user to the database if the password, pNbr and commonName is associated to user account.
	 * Creates a ActiveUser-object for the duration of the session
	 * @param pNbr person number of user
	 * @param password the hashed password of the user
	 * @param commonName the CN of the x509-cert
	 * @return true if the specified information is correct, false otherwise
	 */
	public boolean logInUser(String pNbr, String password, String commonName) {
		String[] data = db.findUser(pNbr, password, commonName);
		if (data != null) {
			au = new ActiveUser(data[0], data[1], Integer.parseInt(data[2]),
					Integer.parseInt(data[3]));
			return true;
		}
		return false;
	}

	/**The menu accessed by the DatabaseServer.
	 * @param query a RequestObject from the client with the data needed to perform a command
	 * @return a RequestObject to send back to the client
	 */
	public RequestObject menu(RequestObject query) {
		int choice = query.getCommand();
		if (loggedIn()) {
			if (choice == 1)
				return new RequestObject(1, getOwnJournal(), "");
			if (choice == 2)
				return new RequestObject(2, journalFor(query.text1(), "r"), "");
			if (choice == 3)
				return new RequestObject(3, getLog(), "");
			if (choice == 4)
				return new RequestObject(4, getOwnUserInfo(), "");
			if (choice == 5)
				return new RequestObject(5, getUserInfo(query.text1()), "");
			if (choice == 6)
				return new RequestObject(6, journalFor(query.text1(), "m"), "");
			if (choice == 7)
				return new RequestObject(7, createJournal(), "");
			if (choice == 8)
				return new RequestObject(8, deleteJournal(query.text1()), "");
			if (choice == 9)
				return new RequestObject(9, logOff(), "");
		}
		return new RequestObject(0, "valj nagot redigt ist", "");
	}

	/**Returns the ActiveUser's String of the own user data
	 * @return a String of the own user data
	 */
	public String getOwnUserInfo() {
		return getUserInfo(au.getPnbr());
	}

	/** Returns user info to account 
	 * @param pNbr the user's person number
	 * @return String-representation of user info to account
	 */
	public String getUserInfo(String pNbr) {
		if (au.getClearance() == 0 || pNbr.equals(au.getPnbr())) {
			return db.getUser(pNbr);
		}
		return block;
	}

	/**Returns the users journal(s)
	 * @return String of the user's journal(s)
	 */
	public String getOwnJournal() {
		return journalFor(au.getPnbr(), "r");
	}

	/**WARNING: this method is prone to error when trying to insert person number of patient that don't have a journal
	 * Used when trying to read or modify a journal and also keeps log of those events
	 * @param pNbr the person number of the journal(s) to access 
	 * @param type the type of access requested; 'm' or 'r'
	 * @return a String with the journal(s)
	 */
	public String journalFor(String pNbr, String type) {
		Journal[] journals = db.getJournal(pNbr);
		StringBuilder sb = new StringBuilder();
		if (pNbr.equals(au.getPnbr()) || au.getClearance() == 0) {
			for (Journal j : journals) {
				sb.append(j.toString() + "\n");
				db.updateLog(au.getPnbr(), j.getJournalNbr(), type);
			}
			System.out.println(sb.toString());
			return sb.toString() != null ? sb.toString() : pass;
		} else if (au.getClearance() == 1 || au.getClearance() == 2) {
			for (Journal j : journals) {
				if (j.atDivision(au.getDivision())) {
					sb.append(j.toString() + "\n");
					db.updateLog(au.getPnbr(), j.getJournalNbr(), type);
				}
			}
			System.out.println(sb.toString());
			return sb.toString() != null ? sb.toString() : pass;
		}
		return block;
	}

	/**Deletes journal (but really doesn't)
	 * @param journalNbr of the journal to be deleted
	 * @return 'pass' or 'blocked' message
	 */
	public String deleteJournal(String journalNbr) {
		if (au.getClearance() == 0) {
			return pass;
		}
		return block;
	}

	/** Creates journal (semi-implemented)
	 * @return message 'pass' or 'block'
	 */
	public String createJournal() {
		if (au.getClearance() == 1) {
			return pass;
		}
		return block;
	}

	/** Returns the log if ActiveUser is 'Socialstyrelsen'
	 * @return the log or the 'block' message if unauthorized access
	 */
	public String getLog() {
		if (au.getClearance() == 0) {
			StringBuilder sb = new StringBuilder();
			for (String s : db.getLog()) {
				sb.append(s + "\n");
			}
			return new String(sb);
		}
		return block;
	}

	/** Method to log off user
	 * @return always "You're logged off"
	 */
	public String logOff() {
		au = null;
		db.closeConnection();
		return "You're logged off";
	}

	/**Method to look for a active user
	 * @return true if there's an ActiveUser object in the database-guard, false otherwise
	 */
	public boolean loggedIn() {
		return au != null;
	}
}
